//
//  SelectorEncodingPreprocessorTest.m
//  test_simple_project
//
//  选择器、编码和预处理器指令测试实现 - 修复版本
//

#import "SelectorEncodingPreprocessorTest.h"
#import <objc/runtime.h>

// 文件级别的pragma指令
#pragma mark - Implementation

@implementation SelectorEncodingPreprocessorTest

- (instancetype)init {
    self = [super init];
    if (self) {
        _target = [[SelectorTestHelper alloc] init];
        _cachedSelector = @selector(helperMethod);
        _encodingInfo = @"";
    }
    return self;
}

#pragma mark - Selector Testing Methods

- (void)testBasicSelectors {
    // 基本选择器创建和比较
    SEL sel1 = @selector(testBasicSelectors);
    SEL sel2 = @selector(helperMethod);
    SEL sel3 = @selector(methodWithParameter:);  // 修复: 使用存在的方法
    
    NSLog(@"Selector 1: %@", NSStringFromSelector(sel1));
    NSLog(@"Selector 2: %@", NSStringFromSelector(sel2));
    NSLog(@"Selector 3: %@", NSStringFromSelector(sel3));
    
    // 选择器比较
    BOOL isEqual = (sel1 == sel2);
    NSLog(@"Selectors equal: %@", isEqual ? @"YES" : @"NO");
}

- (void)testSelectorComparison {
    SEL sel1 = @selector(helperMethod);
    SEL sel2 = NSSelectorFromString(@"helperMethod");
    SEL sel3 = @selector(helperMethod);
    
    NSLog(@"sel1 == sel2: %@", (sel1 == sel2) ? @"YES" : @"NO");
    NSLog(@"sel1 == sel3: %@", (sel1 == sel3) ? @"YES" : @"NO");
    NSLog(@"sel2 == sel3: %@", (sel2 == sel3) ? @"YES" : @"NO");
}

- (void)testSelectorFromString {
    NSString *selectorString = @"helperMethod";
    SEL dynamicSelector = NSSelectorFromString(selectorString);
    SEL staticSelector = @selector(helperMethod);
    
    NSLog(@"Dynamic selector: %@", NSStringFromSelector(dynamicSelector));
    NSLog(@"Static selector: %@", NSStringFromSelector(staticSelector));
    NSLog(@"Are equal: %@", (dynamicSelector == staticSelector) ? @"YES" : @"NO");
}

- (void)testSelectorValidation {
    SEL validSelector = @selector(helperMethod);
    SEL invalidSelector = NSSelectorFromString(@"nonExistentMethod");
    
    BOOL validResponds = [self.target respondsToSelector:validSelector];
    BOOL invalidResponds = [self.target respondsToSelector:invalidSelector];
    
    NSLog(@"Target responds to valid selector: %@", validResponds ? @"YES" : @"NO");
    NSLog(@"Target responds to invalid selector: %@", invalidResponds ? @"YES" : @"NO");
}

- (void)testDynamicSelectorInvocation {
    SEL simpleSelector = @selector(helperMethod);
    SEL parameterSelector = @selector(methodWithParameter:);
    
    // 安全调用无参数方法
    if ([self.target respondsToSelector:simpleSelector]) {
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [self.target performSelector:simpleSelector];
        #pragma clang diagnostic pop
    }
    
    // 安全调用带参数方法
    if ([self.target respondsToSelector:parameterSelector]) {
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        [self.target performSelector:parameterSelector withObject:@"Test Parameter"];
        #pragma clang diagnostic pop
    }
}

- (void)testSelectorWithParameters:(NSString *)param1 andValue:(NSNumber *)param2 {
    NSLog(@"Method called with parameters: %@, %@", param1, param2);
}

- (NSString *)selectorReturningValue {
    return @"Returned from selector method";
}

- (void)testSelectorResponds {
    SEL requiredSelector = @selector(requiredMethodForSelectorTest);
    SEL optionalSelector = @selector(optionalMethodForSelectorTest);
    
    id<SelectorTestProtocol> protocolObject = (id<SelectorTestProtocol>)self.target;
    
    BOOL respondsToRequired = [protocolObject respondsToSelector:requiredSelector];
    BOOL respondsToOptional = [protocolObject respondsToSelector:optionalSelector];
    
    NSLog(@"Responds to required method: %@", respondsToRequired ? @"YES" : @"NO");
    NSLog(@"Responds to optional method: %@", respondsToOptional ? @"YES" : @"NO");
}

- (void)testOptionalSelectorCalls {
    SEL optionalSelector = @selector(optionalMethodWithReturn);
    
    id<SelectorTestProtocol> protocolObject = (id<SelectorTestProtocol>)self.target;
    
    if ([protocolObject respondsToSelector:optionalSelector]) {
        #pragma clang diagnostic push
        #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
        NSString *result = [protocolObject performSelector:optionalSelector];
        #pragma clang diagnostic pop
        NSLog(@"Optional method result: %@", result);
    } else {
        NSLog(@"Optional method not implemented");
    }
}

#pragma mark - Encoding Testing Methods

- (void)testBasicTypeEncoding {
    // 获取基本类型的编码信息
    NSLog(@"char encoding: %s", @encode(char));
    NSLog(@"int encoding: %s", @encode(int));
    NSLog(@"float encoding: %s", @encode(float));
    NSLog(@"double encoding: %s", @encode(double));
    NSLog(@"BOOL encoding: %s", @encode(BOOL));
    NSLog(@"NSInteger encoding: %s", @encode(NSInteger));
    NSLog(@"NSString* encoding: %s", @encode(NSString*));
    NSLog(@"id encoding: %s", @encode(id));
    NSLog(@"Class encoding: %s", @encode(Class));
    NSLog(@"SEL encoding: %s", @encode(SEL));
}

- (void)testStructureEncoding {
    NSLog(@"TestStructure encoding: %s", @encode(TestStructure));
    NSLog(@"ComplexStructure encoding: %s", @encode(ComplexStructure));
    NSLog(@"CGPoint encoding: %s", @encode(CGPoint));
    NSLog(@"CGSize encoding: %s", @encode(CGSize));
    NSLog(@"CGRect encoding: %s", @encode(CGRect));
    NSLog(@"NSRange encoding: %s", @encode(NSRange));
}

- (void)testPointerEncoding {
    NSLog(@"char* encoding: %s", @encode(char*));
    NSLog(@"int* encoding: %s", @encode(int*));
    NSLog(@"void* encoding: %s", @encode(void*));
    // 修复: 使用 __strong 明确指定所有权
    NSLog(@"NSString* __strong * encoding: %s", @encode(NSString* __strong *));
}

- (void)testProtocolEncoding {
    NSLog(@"Protocol encoding: %s", @encode(Protocol*));
    NSLog(@"SelectorTestProtocol encoding: %s", @encode(id<SelectorTestProtocol>));
}

- (void)testMethodSignatures {
    // 获取方法签名信息
    Method method1 = class_getInstanceMethod([self class], @selector(testBasicSelectors));
    Method method2 = class_getInstanceMethod([self class], @selector(testSelectorWithParameters:andValue:));
    
    if (method1) {
        const char *types1 = method_getTypeEncoding(method1);  // 修复: 使用const char*
        NSLog(@"testBasicSelectors method signature: %s", types1);
    }
    
    if (method2) {
        const char *types2 = method_getTypeEncoding(method2);  // 修复: 使用const char*
        NSLog(@"testSelectorWithParameters:andValue: method signature: %s", types2);
    }
}

- (void)testComplexMethodSignature:(NSString *)string 
                           integer:(NSInteger)integer 
                             block:(void(^)(NSString *))block {
    NSLog(@"Complex method called with: %@, %ld", string, (long)integer);
    if (block) {
        block(@"Block executed");
    }
}

#pragma mark - Preprocessor Testing Methods

- (void)testConditionalCompilation {
    NSLog(@"Platform string: %@", PLATFORM_SPECIFIC_STRING);
    NSLog(@"Supports modern API: %@", SUPPORTS_MODERN_API ? @"YES" : @"NO");
}

- (void)testPlatformSpecificCode {
#if TARGET_OS_IOS
    NSLog(@"Running on iOS platform");
#elif TARGET_OS_MAC
    NSLog(@"Running on macOS platform");
#else
    NSLog(@"Running on unknown platform");
#endif
}

- (void)testVersionSpecificCode {
#if SUPPORTS_MODERN_API
    NSLog(@"Modern API is supported");
    [self modernAPIMethod];
#else
    NSLog(@"Modern API is not supported");
#endif
}

- (void)testMacroDefinitions {
    NSLog(@"Max retry count: %d", MAX_RETRY_COUNT);
    NSLog(@"Default timeout: %.1f", DEFAULT_TIMEOUT);
    NSLog(@"Log enabled: %@", LOG_ENABLED ? @"YES" : @"NO");
}

- (void)testParameterizedMacros {
    // 修复: 使用正确的对象类型
    SAFE_PERFORM_SELECTOR(self.target, @selector(helperMethod));
    
    // 测试字符串化宏
    NSString *stringified = @TO_STRING(MAX_RETRY_COUNT);
    NSLog(@"Stringified macro: %@", stringified);
}

- (void)testStringifyMacros {
    NSLog(@"STRINGIFY test: %s", STRINGIFY(Hello World));
    NSLog(@"TO_STRING test: %@", @TO_STRING(TEST_VALUE));
}

- (void)testPragmaDirectives {
    NSLog(@"Testing pragma directives - check source code organization");
}

#pragma mark - Runtime Inspection Methods

- (void)testRuntimeClassInspection {
    Class testClass = [SelectorTestHelper class];
    
    NSLog(@"Class name: %s", class_getName(testClass));
    NSLog(@"Superclass: %s", class_getName(class_getSuperclass(testClass)));
    NSLog(@"Instance size: %zu", class_getInstanceSize(testClass));
    
    unsigned int methodCount;
    Method *methods = class_copyMethodList(testClass, &methodCount);
    NSLog(@"Method count: %u", methodCount);
    
    for (unsigned int i = 0; i < methodCount; i++) {
        SEL selector = method_getName(methods[i]);
        NSLog(@"Method %u: %@", i, NSStringFromSelector(selector));
    }
    
    free(methods);
}

- (void)testRuntimeMethodInspection {
    Method method = class_getInstanceMethod([SelectorTestHelper class], @selector(helperMethod));
    
    if (method) {
        SEL selector = method_getName(method);
        const char *typeEncoding = method_getTypeEncoding(method);  // 修复: 使用const char*
        IMP implementation = method_getImplementation(method);
        
        NSLog(@"Method selector: %@", NSStringFromSelector(selector));
        NSLog(@"Method type encoding: %s", typeEncoding);
        NSLog(@"Method implementation: %p", implementation);
    }
}

- (void)testRuntimePropertyInspection {
    unsigned int propertyCount;
    objc_property_t *properties = class_copyPropertyList([self class], &propertyCount);
    
    NSLog(@"Property count: %u", propertyCount);
    
    for (unsigned int i = 0; i < propertyCount; i++) {
        const char *propertyName = property_getName(properties[i]);
        const char *propertyAttributes = property_getAttributes(properties[i]);
        
        NSLog(@"Property %u: %s, attributes: %s", i, propertyName, propertyAttributes);
    }
    
    free(properties);
}

- (void)testRuntimeProtocolInspection {
    Protocol *protocol = @protocol(SelectorTestProtocol);
    
    NSLog(@"Protocol name: %s", protocol_getName(protocol));
    
    unsigned int methodCount;
    struct objc_method_description *methods = protocol_copyMethodDescriptionList(protocol, YES, YES, &methodCount);
    
    NSLog(@"Required instance method count: %u", methodCount);
    
    for (unsigned int i = 0; i < methodCount; i++) {
        NSLog(@"Required method %u: %@", i, NSStringFromSelector(methods[i].name));
    }
    
    free(methods);
}

#pragma mark - Preprocessor Condition Testing

#if SUPPORTS_MODERN_API
- (void)modernAPIMethod {
    NSLog(@"Modern API method called");
}
#endif

#ifdef DEBUG
- (void)debugOnlyMethod {
    NSLog(@"Debug only method called");
}
#endif

#ifndef NDEBUG
- (void)debugModeMethod {
    NSLog(@"Debug mode method called");
}
#endif

@end

#pragma mark - SelectorTestHelper Implementation

@implementation SelectorTestHelper

- (void)helperMethod {
    NSLog(@"Helper method called");
}

- (void)methodWithParameter:(NSString *)parameter {
    NSLog(@"Method with parameter called: %@", parameter);
}

- (NSString *)methodReturningString {
    return @"String returned from helper method";
}

- (void)methodWithMultipleParameters:(NSString *)string
                              number:(NSNumber *)number
                               array:(NSArray *)array {
    NSLog(@"Method with multiple parameters: %@, %@, %@", string, number, array);
}

#pragma mark - SelectorTestProtocol Implementation

- (void)requiredMethodForSelectorTest {
    NSLog(@"Required protocol method called");
}

- (void)optionalMethodForSelectorTest {
    NSLog(@"Optional protocol method called");
}

- (NSString *)optionalMethodWithReturn {
    return @"Optional method with return value";
}

@end

#pragma mark - Global Functions Implementation

void GlobalFunctionForTesting(void) {
    NSLog(@"Global function for testing called");
}

NSString *GlobalFunctionWithReturn(NSString *input) {
    return [NSString stringWithFormat:@"Global function processed: %@", input];
}

void GlobalFunctionWithParameters(int value1, float value2, const char *string) {
    NSLog(@"Global function with parameters: %d, %.2f, %s", value1, value2, string);
}
